package com.example.javapoet.demo.basic;

import com.squareup.javapoet.*;

import javax.lang.model.element.Modifier;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * JavaPoet基础示例 - 生成基本的Java类
 */
public class BasicClassGeneration {

    public static void main(String[] args) {
        // 生成一个简单的Person类
        generatePersonClass();
        
        // 生成一个带构造函数的类
        generateClassWithConstructor();
        
        // 生成一个带方法的类
        generateClassWithMethods();
    }

    /**
     * 生成一个简单的Person类
     */
    public static void generatePersonClass() {
        // 创建字段
        FieldSpec nameField = FieldSpec.builder(String.class, "name")
                .addModifiers(Modifier.PRIVATE)
                .build();
        
        FieldSpec ageField = FieldSpec.builder(int.class, "age")
                .addModifiers(Modifier.PRIVATE)
                .build();
        
        // 创建getter和setter方法
        MethodSpec getNameMethod = MethodSpec.methodBuilder("getName")
                .addModifiers(Modifier.PUBLIC)
                .returns(String.class)
                .addStatement("return name")
                .build();
        
        MethodSpec setNameMethod = MethodSpec.methodBuilder("setName")
                .addModifiers(Modifier.PUBLIC)
                .returns(void.class)
                .addParameter(String.class, "name")
                .addStatement("this.name = name")
                .build();
        
        MethodSpec getAgeMethod = MethodSpec.methodBuilder("getAge")
                .addModifiers(Modifier.PUBLIC)
                .returns(int.class)
                .addStatement("return age")
                .build();
        
        MethodSpec setAgeMethod = MethodSpec.methodBuilder("setAge")
                .addModifiers(Modifier.PUBLIC)
                .returns(void.class)
                .addParameter(int.class, "age")
                .addStatement("this.age = age")
                .build();
        
        // 创建类
        TypeSpec personClass = TypeSpec.classBuilder("Person")
                .addModifiers(Modifier.PUBLIC)
                .addField(nameField)
                .addField(ageField)
                .addMethod(getNameMethod)
                .addMethod(setNameMethod)
                .addMethod(getAgeMethod)
                .addMethod(setAgeMethod)
                .build();
        
        // 创建Java文件
        JavaFile javaFile = JavaFile.builder("com.example.model", personClass)
                .build();

        try {
            // 输出到控制台
            System.out.println("生成Person类:");
            javaFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            javaFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成Person.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成一个带构造函数的类
     */
    public static void generateClassWithConstructor() {
        // 创建字段
        FieldSpec idField = FieldSpec.builder(long.class, "id")
                .addModifiers(Modifier.PRIVATE, Modifier.FINAL)
                .build();
        
        FieldSpec titleField = FieldSpec.builder(String.class, "title")
                .addModifiers(Modifier.PRIVATE)
                .build();
        
        FieldSpec contentField = FieldSpec.builder(String.class, "content")
                .addModifiers(Modifier.PRIVATE)
                .build();
        
        // 创建构造函数
        MethodSpec constructor = MethodSpec.constructorBuilder()
                .addModifiers(Modifier.PUBLIC)
                .addParameter(long.class, "id")
                .addParameter(String.class, "title")
                .addStatement("this.id = id")
                .addStatement("this.title = title")
                .build();
        
        // 创建另一个构造函数（重载）
        MethodSpec fullConstructor = MethodSpec.constructorBuilder()
                .addModifiers(Modifier.PUBLIC)
                .addParameter(long.class, "id")
                .addParameter(String.class, "title")
                .addParameter(String.class, "content")
                .addStatement("this.id = id")
                .addStatement("this.title = title")
                .addStatement("this.content = content")
                .build();
        
        // 创建getter方法
        MethodSpec getIdMethod = MethodSpec.methodBuilder("getId")
                .addModifiers(Modifier.PUBLIC)
                .returns(long.class)
                .addStatement("return id")
                .build();
        
        MethodSpec getTitleMethod = MethodSpec.methodBuilder("getTitle")
                .addModifiers(Modifier.PUBLIC)
                .returns(String.class)
                .addStatement("return title")
                .build();
        
        MethodSpec getContentMethod = MethodSpec.methodBuilder("getContent")
                .addModifiers(Modifier.PUBLIC)
                .returns(String.class)
                .addStatement("return content")
                .build();
        
        // 创建setter方法（注意：id是final，所以没有setter）
        MethodSpec setTitleMethod = MethodSpec.methodBuilder("setTitle")
                .addModifiers(Modifier.PUBLIC)
                .returns(void.class)
                .addParameter(String.class, "title")
                .addStatement("this.title = title")
                .build();
        
        MethodSpec setContentMethod = MethodSpec.methodBuilder("setContent")
                .addModifiers(Modifier.PUBLIC)
                .returns(void.class)
                .addParameter(String.class, "content")
                .addStatement("this.content = content")
                .build();
        
        // 创建类
        TypeSpec articleClass = TypeSpec.classBuilder("Article")
                .addModifiers(Modifier.PUBLIC)
                .addField(idField)
                .addField(titleField)
                .addField(contentField)
                .addMethod(constructor)
                .addMethod(fullConstructor)
                .addMethod(getIdMethod)
                .addMethod(getTitleMethod)
                .addMethod(getContentMethod)
                .addMethod(setTitleMethod)
                .addMethod(setContentMethod)
                .build();
        
        // 创建Java文件
        JavaFile javaFile = JavaFile.builder("com.example.model", articleClass)
                .build();

        try {
            // 输出到控制台
            System.out.println("\n生成Article类:");
            javaFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            javaFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成Article.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成一个带方法的类
     */
    public static void generateClassWithMethods() {
        // 创建字段
        FieldSpec balanceField = FieldSpec.builder(double.class, "balance")
                .addModifiers(Modifier.PRIVATE)
                .initializer("0.0")
                .build();
        
        FieldSpec ownerField = FieldSpec.builder(String.class, "owner")
                .addModifiers(Modifier.PRIVATE, Modifier.FINAL)
                .build();
        
        FieldSpec accountNumberField = FieldSpec.builder(String.class, "accountNumber")
                .addModifiers(Modifier.PRIVATE, Modifier.FINAL)
                .build();
        
        // 创建构造函数
        MethodSpec constructor = MethodSpec.constructorBuilder()
                .addModifiers(Modifier.PUBLIC)
                .addParameter(String.class, "owner")
                .addParameter(String.class, "accountNumber")
                .addStatement("this.owner = owner")
                .addStatement("this.accountNumber = accountNumber")
                .build();
        
        // 创建业务方法
        MethodSpec depositMethod = MethodSpec.methodBuilder("deposit")
                .addModifiers(Modifier.PUBLIC)
                .returns(boolean.class)
                .addParameter(double.class, "amount")
                .beginControlFlow("if (amount <= 0)")
                .addStatement("return false")
                .endControlFlow()
                .addStatement("this.balance += amount")
                .addStatement("return true")
                .build();
        
        MethodSpec withdrawMethod = MethodSpec.methodBuilder("withdraw")
                .addModifiers(Modifier.PUBLIC)
                .returns(boolean.class)
                .addParameter(double.class, "amount")
                .beginControlFlow("if (amount <= 0)")
                .addStatement("return false")
                .endControlFlow()
                .beginControlFlow("if (balance < amount)")
                .addStatement("return false")
                .endControlFlow()
                .addStatement("this.balance -= amount")
                .addStatement("return true")
                .build();
        
        MethodSpec getBalanceMethod = MethodSpec.methodBuilder("getBalance")
                .addModifiers(Modifier.PUBLIC)
                .returns(double.class)
                .addStatement("return balance")
                .build();
        
        MethodSpec getOwnerMethod = MethodSpec.methodBuilder("getOwner")
                .addModifiers(Modifier.PUBLIC)
                .returns(String.class)
                .addStatement("return owner")
                .build();
        
        MethodSpec getAccountNumberMethod = MethodSpec.methodBuilder("getAccountNumber")
                .addModifiers(Modifier.PUBLIC)
                .returns(String.class)
                .addStatement("return accountNumber")
                .build();
        
        // 创建toString方法
        MethodSpec toStringMethod = MethodSpec.methodBuilder("toString")
                .addAnnotation(Override.class)
                .addModifiers(Modifier.PUBLIC)
                .returns(String.class)
                .addStatement("return $S + owner + $S + accountNumber + $S + balance", 
                        "BankAccount{owner='", "', accountNumber='", "', balance=")
                .addStatement("+ $S", "}")
                .build();
        
        // 创建类
        TypeSpec bankAccountClass = TypeSpec.classBuilder("BankAccount")
                .addModifiers(Modifier.PUBLIC)
                .addField(balanceField)
                .addField(ownerField)
                .addField(accountNumberField)
                .addMethod(constructor)
                .addMethod(depositMethod)
                .addMethod(withdrawMethod)
                .addMethod(getBalanceMethod)
                .addMethod(getOwnerMethod)
                .addMethod(getAccountNumberMethod)
                .addMethod(toStringMethod)
                .build();
        
        // 创建Java文件
        JavaFile javaFile = JavaFile.builder("com.example.model", bankAccountClass)
                .build();

        try {
            // 输出到控制台
            System.out.println("\n生成BankAccount类:");
            javaFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            javaFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成BankAccount.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}